package system

import (
	"fmt"
	"time"

	"github.com/shaocongcong/apollo/agent"
	"github.com/shaocongcong/apollo/plugins/data/system"
	"go.uber.org/zap"
)

// MemStats  ...
type MemStats struct {
	ps        PS
	stop      chan bool
	appname   string
	Interval  int    `toml:"interval"`
	TransName string `toml:"trans_name"`
}

func (mem *MemStats) Gather() error {
	vm, err := mem.ps.VMStat()
	if err != nil {
		return fmt.Errorf("error getting virtual memory info: %s", err)
	}

	fields := map[string]interface{}{
		"available":         int64(vm.Available),
		"available_percent": int64(100 * float64(vm.Available) / float64(vm.Total)),
	}

	metric := &system.Metric{
		Name:     "mem",
		Fields:   fields,
		Time:     time.Now().Unix(),
		Interval: mem.Interval,
		Tags:     make(map[string]string),
	}

	metric.Tags["app"] = mem.appname

	// log.Println("采集3 tags", metric)
	// log.Println("采集3 fields", metric.Fields)
	agent.Writer(mem.TransName, []*system.Metric{metric})
	return nil
}

func (mem *MemStats) start() error {
	mem.appname = agent.Name()
	ticker := time.NewTicker(time.Duration(mem.Interval) * time.Second)
	defer func() {
		if err := recover(); err != nil {
			agent.Logger.Error("mem init", zap.Any("err", err))
		}
	}()
	defer ticker.Stop()

	for {
		select {
		case <-mem.stop:
			return nil
		case <-ticker.C:
			mem.Gather()
			continue
		}
	}
}

// Init ...
func (mem *MemStats) Init() error {
	go mem.start()
	return nil
}

// Start ...
func (mem *MemStats) Start() error {
	return nil
}

// Close ...
func (mem *MemStats) Close() error {
	mem.stop <- true
	return nil
}

func init() {
	agent.AddCollector("mem", &MemStats{
		stop: make(chan bool, 1),
		ps:   &systemPS{},
	})
}
